#pragma once
#include <SceneGraph.h>

namespace grflib
{
    namespace engine
    {
        namespace aux
        {
            template<typename TObj, typename TRenderQueue>
            class COctreeFake : public grflib::engine::core::CSceneGraph<TObj, TRenderQueue>
            {
            public:
                explicit COctreeFake(void) {}
                virtual ~COctreeFake(void) {}

                //add object to manager
                virtual bool AddObj(TObj *pObj) {m_store.push_back(pObj); return true;}

                //remove an object from manager
                virtual void RemoveObj(TObj *pObj);

                //remove all objects from manager
                virtual void Clear(void) {m_store.clear();}

                //update rendering queue according to viewer/obj positions
                virtual void Update(TRenderQueue &renderQueue /*... may require more arguments*/);

                virtual boost::shared_ptr<TObj> GetIntersectedObj(const float3& src, const float3& dir) {return 0;}

                //Visibility Func
            virtual void IsVisible(size_t index) {}

                //traverse interface
                virtual HRESULT Traverse(const grflib::engine::core::IMemberCaller<TObj>& func);
                //virtual HRESULT Traverse(const grflib::engine::core::IMemberPtrCaller<TObj>& func);

            protected:
                //private methods

            protected:
                //data members
                std::vector<TObj *> m_store;
            };

            template<typename TObj, typename TRenderQueue>
            void COctreeFake<TObj, TRenderQueue>::RemoveObj(TObj *pObj)
            {
                for (std::vector<TObj *>::iterator iter = m_store.begin();
                    iter != m_store.end();
                    ++iter)
                {
                    if ((*iter) == pObj)
                        m_store.erase(iter);
                }
            }

            template<typename TObj, typename TRenderQueue>
            HRESULT COctreeFake<TObj, TRenderQueue>::Traverse(const grflib::engine::core::IMemberCaller<TObj>& func)
            {
                HRESULT hr = S_OK;
                BOOST_FOREACH(TObj *pObj, m_store)
                {
                    V_RETURN( func(pObj) );
                }
                return hr;
            }

            //template<typename TObj, typename TRenderQueue>
            //HRESULT COctreeFake<TObj, TRenderQueue>::Traverse(const grflib::engine::core::IMemberPtrCaller<TObj>& func)
            //{
            //    HRESULT hr = S_OK;
            //    BOOST_FOREACH(TObj *&pObj, m_store)
            //    {
            //        V_RETURN( func(&pObj) );
            //    }
            //    return hr;
            //}

            template<typename TObj, typename TRenderQueue>
            void COctreeFake<TObj, TRenderQueue>::Update(TRenderQueue &renderQueue)
            {
                using namespace grflib::engine::core;
                D3DXMATRIX worldMat;
                BOOST_FOREACH(TObj *pObj, m_store)
                {
                    if (pObj->Visible())
                    {
                        const std::vector<IRenderable *> &renderables = pObj->GetRenderables();
                        worldMat = pObj->UpdateWorldMat(worldMat);
                        BOOST_FOREACH(IRenderable *pRenderable, renderables)
                        {
                            renderQueue.push_back( std::make_pair<IRenderable *, D3DXMATRIX>(pRenderable, worldMat) );
                        }
                    }
                }
            }
        } //namespace aux
    } //namespace engine
} //namespace grflib
